package com.yanqu.road.server.manger.activity.busyfarming;

import com.yanqu.road.entity.activity.ActivityConditionInfo;
import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.busyfarming.*;
import com.yanqu.road.entity.activity.busyfarming.enums.eBusyFarmingLandState;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogBusyFarmingSteal;
import com.yanqu.road.entity.log.LogBusyFarmingWatering;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.logic.bussiness.activity.BusyFarmingBusiness;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.activity.BusyFarmingProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.busyfarming.BusyFarmingModule;
import com.yanqu.road.server.gameplayer.module.activity.busyfarming.BusyFarmingPb;
import com.yanqu.road.server.manger.ServerLanguageMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

public class BusyFarmingMgr extends TempMgr {

    public static ActivityInfo activityInfo;

    public static int CROSS_RANK_CONDITION_TYPE = 1032;

    private static Map<Long, BusyFarmingUserData> userDataMap = new ConcurrentHashMap<>();
    //所有土地数
    public static int ALL_LAND_NUM = 9;
    //默认已解锁土地数
    public static int UN_LOCKED_LAND_NUM = 4;

    //亲友酬谢 自增ID
    private static AtomicLong userRewardDbId;

    //亲友来助 自增ID
    private static AtomicLong userHelpDbId;

    //被偷记录 自增ID
    private static AtomicLong userStolenDbId;

    //user
    private static Map<Long, List<BusyFarmingHelpRecord>> userHelpRecordMap = new ConcurrentHashMap<>();
    //user
    private static Map<Long, List<BusyFarmingUserReward>> userRewardMap = new ConcurrentHashMap<>();
    //user
    private static Map<Long, List<BusyFarmingStolenRecord>> userStolenRecordMap = new ConcurrentHashMap<>();
    /**
     * 果园等级配置
     */
    private static List<BusyFarmingGradeInfo> gradeInfoList;
    /**
     * 水果币id
     */
    public static int BUSY_FARMING_FRUIT_SCORE_ID = 101941;
    /**
     * 肥料id
     */
    public static int BUSY_FARMING_MANURE_ID = 120316;
    /**
     * 种子id
     */
    private static List<Integer> BUSY_FARMING_SEED_GOODS;
    /**
     * 水果id
     */
    private static List<Integer> BUSY_FARMING_FRUIT_GOODS;
    /**
     * 浇水参数(次数|催熟时间(小时)|奖励(被浇水果的产量的千分比)|被浇水次数)
     */
    private static List<Integer> BUSY_FARMING_WATERING_PARAM;
    /**
     * 偷水果参数(被偷者等级范围|每日偷取次数|偷取产量的千分比下限|偷取产量的千分比上限)
     */
    private static List<Integer> BUSY_FARMING_STOLEN_PARAM;
    /**
     * 被偷水果参数(被偷取次数|果苗被偷取损失次数)
     */
    private static List<Integer>  BUSY_FARMING_BE_STOLEN_PARAM;
    /**
     * 解锁一键施肥/果园等级
     */
    public static int BUSY_FARMING_ONE_KEY_MANURE_GRADE = 3;
    /**
     * 元宝购买种子库存提示值
     */
    public static int BUSY_FARMING_SEED_STOCK_TIPS_VAL = 10;
    /**
     * 回收折价千分比(未种植种子，未成熟果实，未出售果实）
     */
    public static int BUSY_FARMING_RECOVERY_DISCOUNT = 800;
    /**
     * 解锁土地消耗/元宝
     */
    public static List<Integer> BUSY_FARMING_LAND_OPEN_CONSUME;
    /**
     * 时间参数（偷水果开放时间|耕作时间-早、晚）
     */
    private static List<Integer> BUSY_FARMING_OPT_OPEN_TIME_PARAM;
    /**
     * 来助、失窃保留数据量
     */
    public static int RETAIN_RECORD_DATA_NUM = 50;
    /**
     * 酬谢保留数据量
     */
    public static int RETAIN_REWARD_DATA_NUM = 200;
    /**
     * 机器人生成果园等级范围|土地个数范围
     */
    private static List<Integer> BUSY_FARMING_ROBOT_GARDEN_RANGE;

    /**
     * 是否清除跨服数据（领奖期）
     */
    public static boolean hasClearCrossDataInRewardPeriod;

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean save() {

        for(Map.Entry<Long, BusyFarmingUserData> entry : userDataMap.entrySet()){
            if(entry.getValue().isInsertOption()){
                BusyFarmingBusiness.addBusyFarmingUserData(entry.getValue());
            }else if(entry.getValue().isUpdateOption()){
                BusyFarmingBusiness.updateBusyFarmingUserData(entry.getValue());
            }
        }

        for(Map.Entry<Long, List<BusyFarmingUserReward>> entry : userRewardMap.entrySet()){
            List<BusyFarmingUserReward> list = entry.getValue();
            int size = list.size();
            for(int i = 0; i < size; i++){
                BusyFarmingUserReward reward = list.get(i);
                if(reward.isInsertOption()){
                    BusyFarmingBusiness.addBusyFarmingUserReward(reward);
                }else if(reward.isUpdateOption()){
                    BusyFarmingBusiness.updateBusyFarmingUserReward(reward);
                }
            }
        }

        for(Map.Entry<Long, List<BusyFarmingHelpRecord>> entry : userHelpRecordMap.entrySet()){
            List<BusyFarmingHelpRecord> list = entry.getValue();
            int size = list.size();
            for(int i = 0; i < size; i++){
                BusyFarmingHelpRecord record = list.get(i);
                if(record.isInsertOption()){
                    BusyFarmingBusiness.addBusyFarmingHelpRecord(record);
                }else if(record.isUpdateOption()){
                    BusyFarmingBusiness.updateBusyFarmingHelpRecord(record);
                }
            }
        }

        for(Map.Entry<Long, List<BusyFarmingStolenRecord>> entry : userStolenRecordMap.entrySet()){
            List<BusyFarmingStolenRecord> list = entry.getValue();
            int size = list.size();
            for(int i = 0; i < size; i++){
                BusyFarmingStolenRecord record = list.get(i);
                if(record.isInsertOption()){
                    BusyFarmingBusiness.addBusyFarmingStolenRecord(record);
                }else if(record.isUpdateOption()){
                    BusyFarmingBusiness.updateBusyFarmingStolenRecord(record);
                }
            }
        }

        try{
            removeData();
        }catch (Exception e){
            getLogger().error(e.getMessage(), e);
        }
        return true;
    }

    /**
     * 休息期-移除内存数据
     */
    private void removeData() {
        if(getShowTimeActivityId() == 0){
            return;
        }
        if(!isRestTime()) {
            return;
        }
        int all = 0, num = 0;
        for(Map.Entry<Long, List<BusyFarmingUserReward>> entry : userRewardMap.entrySet()){
            synchronized (getUserLocker(entry.getKey())){
                List<BusyFarmingUserReward> list = entry.getValue();
                while(list.size() > 0){
                    if(list.get(0).isDel()){
                        list.remove(0);
                        all++;
                        num++;
                    }else{
                        break;
                    }
                }
            }
            if(num > 0) {
                getLogger().info("remove {} reward data for user {}", num, entry.getKey());
                num = 0;
            }
        }
        num = 0;
        for(Map.Entry<Long, List<BusyFarmingHelpRecord>> entry : userHelpRecordMap.entrySet()){
            synchronized (getUserLocker(entry.getKey())){
                List<BusyFarmingHelpRecord> list = entry.getValue();
                while(list.size() > 0){
                    if(list.get(0).isDel()){
                        list.remove(0);
                        all++;
                        num++;
                    }else{
                        break;
                    }
                }
            }
            if(num > 0) {
                getLogger().info("remove {} help data for user {}", num, entry.getKey());
                num = 0;
            }
        }
        num = 0;
        for(Map.Entry<Long, List<BusyFarmingStolenRecord>> entry : userStolenRecordMap.entrySet()){
            synchronized (getUserLocker(entry.getKey())){
                List<BusyFarmingStolenRecord> list = entry.getValue();
                while(list.size() > 0){
                    if(list.get(0).isDel()){
                        list.remove(0);
                        all++;
                        num++;
                    }else{
                        break;
                    }
                }
            }
            if(num > 0) {
                getLogger().info("remove {} stolen data for user {}", num, entry.getKey());
                num = 0;
            }
        }
        if(all > 0) {
            getLogger().info("all remove {} data ", all);
        }
    }

    @Override
    public boolean stop() {
        return false;
    }

    public static void reloadActivityData() {
        getLogger().info("reload busy farming activity start");

        // 获取活动
        ActivityInfo tmpActivityInfo;
        List<ActivityInfo> openActivityInfoList = NormalActivityMgr.getOpenActivityInfoList(eActivityType.BusyFarmingActivity.getValue());
        if (openActivityInfoList.size() <= 0) {
            return;
        }
        tmpActivityInfo = openActivityInfoList.get(0);

        List<BusyFarmingGradeInfo> tempGradeInfoList = BusyFarmingBusiness.getGradeInfoList(tmpActivityInfo.getActivityId());

        // 活动配置
        Map<String, ActivityConfig> activityConfigMap = NormalActivityMgr.getActivityConfigMap(tmpActivityInfo.getActivityId());
        if(activityConfigMap != null){
            BUSY_FARMING_FRUIT_SCORE_ID = activityConfigMap.get("BUSY_FARMING_FRUIT_SCORE_ID").getIntValue();
            BUSY_FARMING_SEED_GOODS = StringUtils.stringToIntegerList(activityConfigMap.get("BUSY_FARMING_SEED_GOODS").getValue(), "\\|");
            BUSY_FARMING_FRUIT_GOODS = StringUtils.stringToIntegerList(activityConfigMap.get("BUSY_FARMING_FRUIT_GOODS").getValue(), "\\|");
            BUSY_FARMING_MANURE_ID = activityConfigMap.get("BUSY_FARMING_MANURE_ID").getIntValue();
            BUSY_FARMING_LAND_OPEN_CONSUME = StringUtils.stringToIntegerList(activityConfigMap.get("BUSY_FARMING_LAND_OPEN_CONSUME").getValue(),"\\|");
            BUSY_FARMING_ONE_KEY_MANURE_GRADE = activityConfigMap.get("BUSY_FARMING_ONE_KEY_MANURE_GRADE").getIntValue();
            BUSY_FARMING_SEED_STOCK_TIPS_VAL = activityConfigMap.get("BUSY_FARMING_SEED_STOCK_TIPS_VAL").getIntValue();
            BUSY_FARMING_RECOVERY_DISCOUNT = activityConfigMap.get("BUSY_FARMING_RECOVERY_DISCOUNT").getIntValue();
            BUSY_FARMING_WATERING_PARAM = StringUtils.stringToIntegerList(activityConfigMap.get("BUSY_FARMING_WATERING_PARAM").getValue(), "\\|");
            BUSY_FARMING_STOLEN_PARAM = StringUtils.stringToIntegerList(activityConfigMap.get("BUSY_FARMING_STOLEN_PARAM").getValue(), "\\|");
            BUSY_FARMING_BE_STOLEN_PARAM = StringUtils.stringToIntegerList(activityConfigMap.get("BUSY_FARMING_BE_STOLEN_PARAM").getValue(), "\\|");

            if(activityConfigMap.containsKey("BUSY_FARMING_ROBOT_GARDEN_RANGE")){
                BUSY_FARMING_ROBOT_GARDEN_RANGE = StringUtils.stringToIntegerList(activityConfigMap.get("BUSY_FARMING_ROBOT_GARDEN_RANGE").getValue(), "\\|");
            }else {
                BUSY_FARMING_ROBOT_GARDEN_RANGE = StringUtils.stringToIntegerList("2|2", "\\|");
            }

            if(activityConfigMap.containsKey("BUSY_FARMING_OPT_OPEN_TIME_PARAM")){
                BUSY_FARMING_OPT_OPEN_TIME_PARAM = StringUtils.stringToIntegerList(activityConfigMap.get("BUSY_FARMING_OPT_OPEN_TIME_PARAM").getValue(), "\\|");
            }else {
                BUSY_FARMING_OPT_OPEN_TIME_PARAM = StringUtils.stringToIntegerList("14|10|22", "\\|");
            }
        }
        //重载数据
        if(activityInfo == null || activityInfo.getActivityId() != tmpActivityInfo.getActivityId()){
            userDataMap = BusyFarmingBusiness.getUserDataMap(tmpActivityInfo.getActivityId());
            userHelpRecordMap = BusyFarmingBusiness.getUserHelpRecordMap(tmpActivityInfo.getActivityId());
            userRewardMap = BusyFarmingBusiness.getUserRewardMap(tmpActivityInfo.getActivityId());
            userStolenRecordMap = BusyFarmingBusiness.getUserStolenRecordMap(tmpActivityInfo.getActivityId());

            long maxRewardDbId = BusyFarmingBusiness.getMaxUserRewardDbId(tmpActivityInfo.getActivityId());
            userRewardDbId = new AtomicLong(maxRewardDbId);

            long maxHelpDbId = BusyFarmingBusiness.getMaxUserHelpDbId(tmpActivityInfo.getActivityId());
            userHelpDbId = new AtomicLong(maxHelpDbId);

            long maxStolenDbId = BusyFarmingBusiness.getMaxUserStolenDbId(tmpActivityInfo.getActivityId());
            userStolenDbId = new AtomicLong(maxStolenDbId);

            hasClearCrossDataInRewardPeriod = false;
        }

        activityInfo = tmpActivityInfo;
        gradeInfoList = tempGradeInfoList;

        reloadPlayerData();
        getLogger().info("reload busy farming activity end");
    }

    private static void reloadPlayerData() {
        if (ActivityMgr.activityInShowTime(activityInfo)) {
            for (GamePlayer player : GamePlayerMgr.getCopyPlayerMap().values()) {
                if (SystemOpenMgr.systemOpen(player, eSystemId.BusyFarmingActivity.getValue())) {
                    BusyFarmingModule module = player.getModule(BusyFarmingModule.class);
                    BusyFarmingUserData userData = userDataMap.get(player.getUserId());
                    dailyReset(userData);
                    if (userData == null || userData.getActivityId() != activityInfo.getActivityId()) {
                        module.initUserData();
                        module.syncUserData();
                    }
                }
            }
        }
    }

    public static void dailyReset(BusyFarmingUserData userData) {
        if(userData == null){
            return;
        }
        long today = LocalDateTimeHelper.getZeroTimeTimeStamp();
        long lastResetDay = LocalDateTimeHelper.getZeroTimeTimeStamp(userData.getResetTime());
        if (today > lastResetDay) {
            userData.setWateringTimes(0);
            userData.setBeWateringTimes(0);
            userData.setBeStealTimes(0);
            userData.setStealTimes(0);
            userData.setResetTime(System.currentTimeMillis());
        }
    }

    /**
     * 计算土地状态
     */
    public static void calUserLandState() {
        //无活动或者进入领奖期
        if(activityInfo == null || !ActivityMgr.activityInTime(activityInfo)){
            return;
        }
        int nowTime = DateHelper.getCurrentSecond();
        for(Map.Entry<Long, BusyFarmingUserData> entry : userDataMap.entrySet()){
            try {
                boolean change = false;
                BusyFarmingUserData userData = entry.getValue();
                synchronized (userData) {
                    for (BusyFarmingLand land : userData.getLandMap().values()) {
                        if(calLandState(land, nowTime)){
                            change = true;
                        }
                    }
                }
                if(change){
                    //是否有收获红点
                    if(landHasState(userData, eBusyFarmingLandState.Harvest.getIntValue())){
                        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userData.getUserId());
                        if(player != null){
                            player.getModule(BusyFarmingModule.class).syncRedDot(8, 8);
                        }
                    }
                }
            }catch (Exception e){
                getLogger().error(e.getMessage(), e);
            }
        }
    }

    /**
     * 计算玩家的土地状态
     */
    public static void calLandState(BusyFarmingUserData userData){
        int nowTime = DateHelper.getCurrentSecond();
        for(BusyFarmingLand land : userData.getLandMap().values()){
            calLandState(land, nowTime);
        }
    }

    /**
     * 计算土地状态
     */
    public static boolean calLandState(BusyFarmingLand land, int nowTime) {
        if(land.getStates().contains(eBusyFarmingLandState.Lock.getIntValue()) || land.getStates().contains(eBusyFarmingLandState.Plant.getIntValue())){
            return false;
        }
        if(land.getStates().contains(eBusyFarmingLandState.Harvest.getIntValue())){
            //可偷取
            return false;
        }
        if(land.getGoodsId() == 0){
            return false;
        }
        if(nowTime == 0) {
            nowTime = DateHelper.getCurrentSecond();
        }
        if(nowTime >= land.getHarvestTime()){
            //收获
            land.getStates().clear();
            land.getStates().add(eBusyFarmingLandState.Harvest.getIntValue());
            land.getStates().add(eBusyFarmingLandState.Steal.getIntValue());
            land.setFlorescence(false);
        }else {
            //花期
            boolean isFlorescence = isFlorescence(land, nowTime);
            land.setFlorescence(isFlorescence);
            if(land.getWateringTimes() == 0 && isFlorescence) {
                land.getStates().add(eBusyFarmingLandState.Watering.getIntValue());
            }else {
                land.getStates().remove(eBusyFarmingLandState.Watering.getIntValue());
            }
        }
        return true;
    }

    /**
     * 是否花期
     */
    public static boolean isFlorescence(BusyFarmingLand land, int nowTime) {
        if(nowTime == 0){
            nowTime = DateHelper.getCurrentSecond();
        }
        int leftTime = land.getHarvestTime() - nowTime;
        int totalTime = land.getTotalTime() * 60;
        double percent = BigDecimal.valueOf((long)(totalTime - leftTime)).divide(BigDecimal.valueOf((long)totalTime), 3, BigDecimal.ROUND_UP).doubleValue();
        return  percent>= 0.25 && percent < 1;
    }

    /**
     * 保存来助
     */
    public static void addUserHelpRecord(BusyFarmingHelpRecord record){
        if(!userHelpRecordMap.containsKey(record.getUserId())){
            userHelpRecordMap.put(record.getUserId(), new ArrayList<>());
        }
        List<BusyFarmingHelpRecord> list = userHelpRecordMap.get(record.getUserId());
        if(list.size() >= RETAIN_RECORD_DATA_NUM){
            int len = list.size() - RETAIN_RECORD_DATA_NUM + 1;
            for(int i = 0; i < len; i++){
                list.get(i).setDel(true);
            }
            getLogger().info("mark del user {} help record size {}", record.getUserId(), len);
        }
        record.setDbId(userHelpDbId.incrementAndGet());
        list.add(record);
    }

    /**
     * 保存酬谢
     */
    public static void addUserReward(BusyFarmingUserReward reward){
        if(!userRewardMap.containsKey(reward.getUserId())){
            userRewardMap.put(reward.getUserId(), new ArrayList<>());
        }
        reward.setDbId(userRewardDbId.incrementAndGet());
        List list = userRewardMap.get(reward.getUserId());
        list.add(reward);
    }

    /**
     * 保存失窃记录
     */
    public static void addStolenRecord(BusyFarmingStolenRecord record){
        if(!userStolenRecordMap.containsKey(record.getUserId())){
            userStolenRecordMap.put(record.getUserId(), new ArrayList<>());
        }
        List<BusyFarmingStolenRecord> list = userStolenRecordMap.get(record.getUserId());
        if(list.size() >= RETAIN_RECORD_DATA_NUM){
            int len = list.size() - RETAIN_RECORD_DATA_NUM + 1;
            for(int i = 0; i < len; i++){
                list.get(i).setDel(true);
            }
            getLogger().info("mark del user {} stolen record size {}", record.getUserId(), len);
        }
        record.setDbId(userStolenDbId.incrementAndGet());
        list.add(record);
    }

    /**
     * 跨服通知被偷了
     */
    public static void crossNotifyStolen(int activityId, long userId, int landId, int seedId, long enemyUserId, UserBaseInfo enemyBaseInfo, int num) {
        if(activityId != BusyFarmingMgr.getShowTimeActivityId()){
            return;
        }
        BusyFarmingUserData userData = getBusyFarmingUserData(userId);
        if(userData == null){
            return;
        }
        BusyFarmingLand land = userData.getLandMap().get(landId);
        if(land == null){
            return;
        }
        dealReduction(userData, land, seedId, enemyUserId, enemyBaseInfo, num);
    }

    /**
     * 处理被偷减产,及被偷记录
     */
    public static BusyFarmingStolenRecord dealReduction(BusyFarmingUserData stealUserData, BusyFarmingLand land, int seedId, long enemyUserId, UserBaseInfo enemyBaseInfo, int num) {
        BusyFarmingStolenRecord stolenRecord;
        synchronized (stealUserData){
            //失窃记录
            stolenRecord = new BusyFarmingStolenRecord();
            stolenRecord.setActivityId(BusyFarmingMgr.getShowTimeActivityId());
            stolenRecord.setUserId(stealUserData.getUserId());
            stolenRecord.setEnemyId(enemyUserId);
            stolenRecord.setStolenTime(DateHelper.getCurrentSecond());
            stolenRecord.setEnemyServerId(enemyBaseInfo.getServerId());
            stolenRecord.getParams().add(String.valueOf(enemyBaseInfo.getTitleId()));
            stolenRecord.getParams().add(enemyBaseInfo.getNickName());
            stolenRecord.setLoss("0");
            UserInfo userInfo = UserMgr.getUserInfo(stealUserData.getUserId());
            if(stealUserData.getBeStealTimes() < BusyFarmingMgr.getBusyFarmingBeStolenParam().get(0)){
                if(land.getStolenTimes() < BusyFarmingMgr.getBusyFarmingBeStolenParam().get(1)) {
                    if(land.getGoodsId() == seedId && land.getGoodsId() > 0) {
                        //减产
                        land.setStolenTimes(1 + land.getStolenTimes());
                        land.getReduce().add(num);
                        stealUserData.setBeStealTimes(1 + stealUserData.getBeStealTimes());
                        stolenRecord.getParams().add("" + num);
                        stolenRecord.setLoss("" + num);
                        GoodsInfo goodsInfo = BusyFarmingMgr.getSeedMaturityFruit(seedId);
                        stolenRecord.getParams().add(ServerLanguageMgr.getContent(goodsInfo.getGoodsName(), userInfo.getLanguage()));
                    }
                }
            }
            if(enemyBaseInfo.getServerId() != GameServer.getInstance().getServerId()){
                stolenRecord.setUserBaseInfo(enemyBaseInfo);
            }
        }
        synchronized (getUserLocker(stealUserData.getUserId())){
            if(stolenRecord != null){
                stolenRecord.setInsertOption();
                addStolenRecord(stolenRecord);

                //偷取日志
                LogBusyFarmingSteal stealLog = new LogBusyFarmingSteal(BusyFarmingMgr.getShowTimeActivityId(), enemyUserId, land.getId(), seedId, stealUserData.getUserId(), num, System.currentTimeMillis());
                LogMgr.addLogBusyFarmingSteal(stealLog);
            }
        }
        //被偷红点
        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(stealUserData.getUserId());
        if(gamePlayer != null){
            gamePlayer.getModule(BusyFarmingModule.class).syncRedDot(2, 2);
        }
        return stolenRecord;
    }

    /**
     * 上传 成熟的果园
     */
    public static void uploadUserData() {
        //无活动或者进入领奖期
        if(activityInfo == null || !ActivityMgr.activityInTime(activityInfo)){
            //领奖期，清除跨服数据
            if(ActivityMgr.activityInRewardPeriod(activityInfo) && !hasClearCrossDataInRewardPeriod){
                BusyFarmingProto.CrossUserDataSyncMsg.Builder syncMsg = BusyFarmingProto.CrossUserDataSyncMsg.newBuilder();
                syncMsg.setActivityId(activityInfo.getActivityId());
                GamePlayerMgr.sendPacket(0, YanQuMessageUtils.buildMessage(Protocol.C_BUSY_FARMING_ACTIVITY_SYNC_USER_DATA, syncMsg));
                hasClearCrossDataInRewardPeriod = true;
            }
            return;
        }
        //是否是跨服活动
        if(!isCrossBusyFarmingActivity()){
            return;
        }
        BusyFarmingProto.CrossUserDataSyncMsg.Builder syncMsg = BusyFarmingProto.CrossUserDataSyncMsg.newBuilder();
        syncMsg.setActivityId(activityInfo.getActivityId());
        for(Map.Entry<Long, BusyFarmingUserData> entry : userDataMap.entrySet()){
            //v4.5 成熟的果园或者有商会的玩家 上跨服
            boolean add = false;
            UserInfo userInfo = UserMgr.getUserInfo(entry.getValue().getUserId());
            if(userInfo != null && !StringUtils.isNullOrEmpty(userInfo.getUnionUid())){
                add = true;
            }
            if(!add) {
                if(canWatering(entry.getValue())){
                    add = true;
                }else {
                    for (BusyFarmingLand land : entry.getValue().getLandMap().values()) {
                        if (land.getStates().contains(eBusyFarmingLandState.Harvest.getIntValue())) {
                            add = true;
                            break;
                        }
                    }
                }
            }
            if(!add){
                continue;
            }
            BusyFarmingProto.BusyFarmingUserDataTemp.Builder builder = BusyFarmingPb.getUserDataBuilder(entry.getValue(), true);
            UserBaseInfo userBaseInfo = UserMgr.getUserBaseInfo(entry.getValue().getUserId(), GameServer.getInstance().getServerId());
            builder.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            syncMsg.addUserData(builder);
        }
        GamePlayerMgr.sendPacket(0, YanQuMessageUtils.buildMessage(Protocol.C_BUSY_FARMING_ACTIVITY_SYNC_USER_DATA, syncMsg));
    }

    /**
     * 是否可浇水
     */
    public static boolean canWatering(BusyFarmingUserData userData) {
        //今日无被浇水次数
        if(userData.getBeWateringTimes() >= getBusyFarmingWateringParam().get(3)){
            return false;
        }
        for(BusyFarmingLand land : userData.getLandMap().values()){
           if(land.getStates().contains(eBusyFarmingLandState.Watering.getIntValue()) && land.getWateringTimes() == 0){
               return true;
           }
        }
        return false;
    }

    /**
     * 是否包含某个状态
     */
    public static boolean landHasState(BusyFarmingUserData userData, int state) {
        for(BusyFarmingLand land : userData.getLandMap().values()){
            if(land.getStates().contains(state)){
                return true;
            }
        }
        return false;
    }

    /**
     * 获取种子的成熟时间（分钟）
     */
    public static int getSeedMaturityTime(int goodsId){
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(goodsId);
        if(goodsInfo != null){
            return goodsInfo.getParamList().get(0).intValue() * 60;
        }
        return 0;
    }

    /**
     * 获取肥料的加速时间（分钟）
     */
    public static int getFertilizerQuickenTime(int seedId){
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(seedId);
        if(goodsInfo != null){
            return goodsInfo.getParamList().get(0).intValue();
        }
        return 0;
    }

    /**
     * 获取果园等级
     */
    public static int getGuoYuanGrade(long score){
        int grade = 1;
        for(BusyFarmingGradeInfo gradeInfo : gradeInfoList){
            if(score >=gradeInfo.getIntegral()){
                grade = gradeInfo.getId();
            }
        }
        return grade;
    }

    /**
     * 获取果园等级名称
     */
    public static String getHomeGradeName(int homeGrade, String language) {
        for(BusyFarmingGradeInfo gradeInfo : gradeInfoList){
            if(gradeInfo.getId() == homeGrade){
                return ServerLanguageMgr.getContent(gradeInfo.getName(), language);
            }
        }
        return "";
    }

    /**
     * 获取(单个)成熟水果的积分
     */
    public static int getSeedMaturityFruitScore(int seedId){
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(seedId);
        if(goodsInfo != null){
            goodsInfo = GoodsMgr.getGoodsById(Integer.valueOf(goodsInfo.getExtendParam()));
            if(goodsInfo != null){
                return goodsInfo.getParamList().get(0).intValue();
            }
        }
        return 0;
    }

    /**
     * 获取种子成熟水果的水果币(乘以产量)
     */
    public static long getSeedMaturityFruitScore(int seedId, int radio, int count){
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(seedId);
        if(goodsInfo != null){
            goodsInfo = GoodsMgr.getGoodsById(Integer.valueOf(goodsInfo.getExtendParam()));
            if(goodsInfo != null){
                return BigDecimal.valueOf(goodsInfo.getParamList().get(0).longValue()).multiply(BigDecimal.valueOf(count))
                        .multiply(BigDecimal.valueOf(goodsInfo.getParamList().get(1).longValue()))
                        .multiply(BigDecimal.valueOf((long)radio)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).longValue();
            }
        }
        return 0;
    }

    /**
     * 获取成熟水果产量（+浇水加成）
     */
    public static int getSeedMaturityFruitNum(int seedId, int wateringTimes){
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(seedId);
        if(goodsInfo != null){
            goodsInfo = GoodsMgr.getGoodsById(Integer.valueOf(goodsInfo.getExtendParam()));
            if(goodsInfo != null){
                int score = BigDecimal.valueOf(goodsInfo.getParamList().get(1).longValue()).multiply(BigDecimal.valueOf((long)wateringTimes * goodsInfo.getParamList().get(2).longValue()).add(BigDecimal.valueOf(1000))).
                        divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).intValue();
                return score;
            }
        }
        return 0;
    }

    /**
     * 偷取奖励水果（+浇水加成）,随机
     */
    public static int getStealRewardFruitNum(int seedId, int wateringTimes, int radio){
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(seedId);
        if(goodsInfo != null){
            goodsInfo = GoodsMgr.getGoodsById(Integer.valueOf(goodsInfo.getExtendParam()));
            if(goodsInfo != null){
                int score = BigDecimal.valueOf(goodsInfo.getParamList().get(1).longValue()).multiply(BigDecimal.valueOf((long)wateringTimes * goodsInfo.getParamList().get(2).longValue()).add(BigDecimal.valueOf(1000)))
                        .multiply(BigDecimal.valueOf(radio)).divide(BigDecimal.valueOf(1000000), 0, BigDecimal.ROUND_UP).intValue();
                return score;
            }
        }
        return 0;
    }

    /**
     * 获取浇水奖励（按配置的成熟产量千分比）
     */
    public static int getWateringRewardFruitNum(int seedId, int ratio){
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(seedId);
        if(goodsInfo != null){
            goodsInfo = GoodsMgr.getGoodsById(Integer.valueOf(goodsInfo.getExtendParam()));
            if(goodsInfo != null){
                int score = BigDecimal.valueOf(goodsInfo.getParamList().get(1).longValue()).multiply(BigDecimal.valueOf((long)ratio)).
                        divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).intValue();
                return score;
            }
        }
        return 0;
    }


    /**
     * 获取成熟水果
     */
    public static GoodsInfo getSeedMaturityFruit(int seedId){
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(seedId);
        if(goodsInfo != null){
            goodsInfo = GoodsMgr.getGoodsById(Integer.valueOf(goodsInfo.getExtendParam()));
            if(goodsInfo != null){
                return goodsInfo;
            }
        }
        return null;
    }

    /**
     * 是否跨服活动
     */
    public static boolean isCrossBusyFarmingActivity(){
        List<ActivityConditionInfo> conditionInfoList = NormalActivityMgr.getActivityConditionInfoList(activityInfo.getActivityId());
        if(conditionInfoList == null){
            return false;
        }
        for(ActivityConditionInfo conditionInfo : conditionInfoList){
            if(conditionInfo.getType() == CROSS_RANK_CONDITION_TYPE){
                return true;
            }
        }
        return false;
    }

    /**
     * 获取展示中的活动ID（0表示没活动）
     */
    public static int getShowTimeActivityId() {
        return activityInfo == null ? 0 : activityInfo.getActivityId();
    }

    /**
     * 是否在清空道具时间内
     */
    public static boolean isActivityInClearTime() {
        return ActivityMgr.activityInRewardPeriod(activityInfo);
    }

    /**
     * 是否休息时间
     */
    public static boolean isRestTime() {
        int hours = DateHelper.getHours();
        return hours < BusyFarmingMgr.getBusyFarmingOptOpenTimeParam().get(1) || hours >= BusyFarmingMgr.getBusyFarmingOptOpenTimeParam().get(2);
    }

    /**
     * v4.5
     * 跨服来查看果园详情
     */
    public static int friendHomeDetail(int activityId, long userId, long srcServerId, long srcUserId, boolean canWatering) {

        BusyFarmingUserData userData = BusyFarmingMgr.getBusyFarmingUserData(userId);
        if(userData == null){
            return GameErrorCode.E_BUSY_FARMING_ACTIVITY_NO_UNLOCK;
        }
        synchronized (userData){
            BusyFarmingMgr.calLandState(userData);
        }

        BusyFarmingProto.BusyFarmingFriendHomeDetailCrossRespMsg.Builder respMsg = BusyFarmingProto.BusyFarmingFriendHomeDetailCrossRespMsg.newBuilder();
        respMsg.setActivityId(activityId);
        respMsg.setRet(0);
        respMsg.setSrcServerId(srcServerId);
        respMsg.setSrcUserId(srcUserId);

        BusyFarmingProto.BusyFarmingUserDataTemp.Builder userDataBuilder = BusyFarmingPb.getUserDataBuilder(userData, true);
        //我的浇水次数达上限 或者 对方被浇水次数达上限时
        if(!canWatering || userData.getBeWateringTimes() >= BusyFarmingMgr.getBusyFarmingWateringParam().get(3)){
            userDataBuilder = BusyFarmingPb.getUserDataBuilder(userData, false);
            for (Map.Entry<Integer, BusyFarmingLand> landEntry : userData.getLandMap().entrySet()) {
                //clone
                BusyFarmingLand land = BusyFarmingMgr.cloneLand(landEntry.getValue());
                if(land.getStates().contains(eBusyFarmingLandState.Watering.getIntValue())){
                    land.getStates().remove(eBusyFarmingLandState.Watering.getIntValue());
                }
                userDataBuilder.addLand(BusyFarmingPb.getLandBuilder(land));
            }
        }
        UserBaseInfo userBaseInfo = UserMgr.getUserBaseInfo(userId, GameServer.getInstance().getServerId());
        userDataBuilder.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        userDataBuilder.setUserId(userId);
        respMsg.setFriend(userDataBuilder);
        GamePlayerMgr.sendPacket(0, YanQuMessageUtils.buildMessage(Protocol.C_BUSY_FARMING_FRIEND_HOME_DETAIL_BACK, respMsg));
        return 0;
    }

    /**
     * 浇水 (获得水果道具)
     */
    public static int crossWatering(int activityId, int landId, long userId, long srcServerId, long srcUserId, UserBaseInfo baseInfo) {

        BusyFarmingUserData friendUserData = BusyFarmingMgr.getBusyFarmingUserData(userId);
        if(friendUserData == null){
            return GameErrorCode.E_BUSY_FARMING_ACTIVITY_NO_UNLOCK;
        }
        BusyFarmingLand land = friendUserData.getLandMap().get(landId);
        int nowTime = DateHelper.getCurrentSecond();

        List<Integer> wateringParams = BusyFarmingMgr.getBusyFarmingWateringParam();

        //来助记录
        BusyFarmingHelpRecord record;

        synchronized (friendUserData) {
            BusyFarmingMgr.calLandState(land, nowTime);
            if (!land.getStates().contains(eBusyFarmingLandState.Watering.getIntValue())) {
                return GameErrorCode.E_BUSY_FARMING_ACTIVITY_NO_NEED_WATERING;
            }
            //对方被浇水次数
            if(friendUserData.getBeWateringTimes() >= wateringParams.get(3)){
                return GameErrorCode.E_BUSY_FARMING_ACTIVITY_FRIEND_WATERING_HAD_LIMIT;
            }
            friendUserData.setBeWateringTimes(1 + friendUserData.getBeWateringTimes());

            //浇水+加产量
            land.setWateringTimes(1 + land.getWateringTimes());
            BusyFarmingMgr.calLandState(land, nowTime);
            friendUserData.setUpdateOption();

            GoodsInfo fruitGoods = BusyFarmingMgr.getSeedMaturityFruit(land.getGoodsId());
            int addition = 0;
            if(fruitGoods != null){
                addition = fruitGoods.getParamList().get(2).intValue();
            }
            //来助记录
            record = initHelpRecord(userId, baseInfo, srcUserId, land.getGoodsId(), addition);

            //来助红点
            GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(userId);
            if(gamePlayer != null){
                gamePlayer.getModule(BusyFarmingModule.class).syncRedDot(1, 1);
            }
        }

        synchronized (BusyFarmingMgr.getUserLocker(friendUserData.getUserId())){
            BusyFarmingMgr.addUserHelpRecord(record);

            //浇水日志
            LogBusyFarmingWatering wateringLog = new LogBusyFarmingWatering(BusyFarmingMgr.getShowTimeActivityId(), userId, landId, land.getGoodsId(), srcUserId, System.currentTimeMillis());
            LogMgr.addLogBusyFarmingWatering(wateringLog);
        }

        //酬谢红点
        //syncRedDot(4, 4);

        syncOtherUserData(friendUserData, true);

        BusyFarmingProto.BusyFarmingWateringCrossRespMsg.Builder respMsg = BusyFarmingProto.BusyFarmingWateringCrossRespMsg.newBuilder();
        respMsg.setActivityId(activityId);
        respMsg.setRet(0);
        respMsg.setSrcServerId(srcServerId);
        respMsg.setSrcUserId(srcUserId);
        respMsg.setUserId(userId);
        UserBaseInfo userBaseInfo = UserMgr.getUserBaseInfo(userId, GameServer.getInstance().getServerId());
        respMsg.setLand(BusyFarmingPb.getLandBuilder(land));
        if(userBaseInfo != null) {
            respMsg.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        }
        GamePlayerMgr.sendPacket(0, YanQuMessageUtils.buildMessage(Protocol.C_BUSY_FARMING_WATERING_BACK, respMsg));

        return 0;
    }

    public static void syncOtherUserData(BusyFarmingUserData friendUserData, boolean containLand) {
        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(friendUserData.getUserId());
        if(gamePlayer != null){
            BusyFarmingProto.BusyFarmingUserDataSyncMsg.Builder syncMsg = BusyFarmingProto.BusyFarmingUserDataSyncMsg.newBuilder();
            BusyFarmingProto.BusyFarmingUserDataTemp.Builder dataBuilder = BusyFarmingPb.getUserDataBuilder(friendUserData, containLand);
            syncMsg.setActivityId(BusyFarmingMgr.getShowTimeActivityId());
            syncMsg.setUserData(dataBuilder);
            syncMsg.setConfig(BusyFarmingPb.getBusyFarmingConfigDataTempBuilder(gamePlayer.getLanguage()));
            gamePlayer.sendPacket(Protocol.U_BUSY_FARMING_USER_DATA_SYNC, syncMsg);
        }
    }

    /**
     * 初始来助记录
     */
    private static BusyFarmingHelpRecord initHelpRecord(long userId, UserBaseInfo friendUserInfo, long friendUserId, int seedId, int addition) {
        BusyFarmingHelpRecord record;
        record = new BusyFarmingHelpRecord();
        record.setActivityId(BusyFarmingMgr.getShowTimeActivityId());
        record.setUserId(userId);
        record.setFriendId(friendUserId);
        record.setHelpType(1);
        record.setHelpTime(DateHelper.getCurrentSecond());
        record.getParams().add(String.valueOf(friendUserInfo.getTitleId()));
        record.getParams().add(friendUserInfo.getNickName());
        record.setUserBaseInfo(friendUserInfo);
        GoodsInfo goodsInfo = BusyFarmingMgr.getSeedMaturityFruit(seedId);
        UserInfo userInfo = UserMgr.getUserInfo(userId);
        if(userInfo != null){
            record.getParams().add(ServerLanguageMgr.getContent(goodsInfo.getGoodsName(), userInfo.getLanguage()));
        }else {
            record.getParams().add(goodsInfo.getGoodsName());
        }
        record.getParams().add(String.valueOf(addition));
        record.setInsertOption();
        return record;
    }

    public static boolean activityInTime(){
        return ActivityMgr.activityInTime(activityInfo);
    }

    public static ActivityInfo getActivityInfo() {
        return activityInfo;
    }

    public static Map<Long, BusyFarmingUserData> getUserDataMap() {
        return userDataMap;
    }

    public static BusyFarmingUserData getBusyFarmingUserData(long userId){
        if(userDataMap == null){
            return null;
        }
        return userDataMap.get(userId);
    }

    public static Map<Long, List<BusyFarmingHelpRecord>> getUserHelpRecordMap() {
        return userHelpRecordMap;
    }

    public static List<BusyFarmingHelpRecord> getUserHelpRecord(long userId) {
        if(!userHelpRecordMap.containsKey(userId)){
            return new ArrayList<>();
        }
        return new ArrayList<>(userHelpRecordMap.get(userId));
    }

    public static Map<Long, List<BusyFarmingUserReward>> getUserRewardMap() {
        return userRewardMap;
    }

    public static List<BusyFarmingUserReward> getUserReward(long userId) {
        if(!userRewardMap.containsKey(userId)){
            return new ArrayList<>();
        }
        return new ArrayList<>(userRewardMap.get(userId));
    }

    public static Map<Long, List<BusyFarmingStolenRecord>> getUserStolenRecordMap() {
        return userStolenRecordMap;
    }

    public static List<BusyFarmingStolenRecord> getUserStolenRecord(long userId) {
        if(!userStolenRecordMap.containsKey(userId)){
            return new ArrayList<>();
        }
        return new ArrayList<>(userStolenRecordMap.get(userId));
    }

    public static List<Integer> getBusyFarmingSeedGoods() {
        return BUSY_FARMING_SEED_GOODS;
    }

    public static List<Integer> getBusyFarmingFruitGoods() {
        return BUSY_FARMING_FRUIT_GOODS;
    }

    public static List<Integer> getBusyFarmingWateringParam() {
        return BUSY_FARMING_WATERING_PARAM;
    }

    public static List<Integer> getBusyFarmingOptOpenTimeParam() {
        return BUSY_FARMING_OPT_OPEN_TIME_PARAM;
    }

    public static List<Integer> getBusyFarmingStolenParam() {
        return BUSY_FARMING_STOLEN_PARAM;
    }

    public static List<Integer> getBusyFarmingBeStolenParam() {
        return BUSY_FARMING_BE_STOLEN_PARAM;
    }

    public static List<Integer> getBusyFarmingRobotGardenRange() {
        return BUSY_FARMING_ROBOT_GARDEN_RANGE;
    }

    public static List<BusyFarmingGradeInfo> getGradeInfoList() {
        return gradeInfoList;
    }

    private static Map<Long, Object> userLockerMap = new ConcurrentHashMap<>();

    public static Object getUserLocker(long userId){
        if(!userLockerMap.containsKey(userId)){
            synchronized (userLockerMap){
                if(!userLockerMap.containsKey(userId)){
                    userLockerMap.put(userId, new Object());
                }
            }
        }
        return userLockerMap.get(userId);
    }

    public static BusyFarmingLand cloneLand(BusyFarmingLand land){
        BusyFarmingLand newLand = new BusyFarmingLand();
        newLand.setId(land.getId());
        newLand.setGoodsId(land.getGoodsId());
        newLand.setHarvestTime(land.getHarvestTime());
        newLand.setTotalTime(land.getTotalTime());
        for (int state : land.getStates()) {
            newLand.getStates().add(state);
        }
        newLand.setWateringTimes(land.getWateringTimes());
        newLand.setStolenTimes(land.getStolenTimes());
        newLand.setFlorescence(land.isFlorescence());
        newLand.setQuickenTimes(land.getQuickenTimes());
        for (int i : land.getReduce()) {
            newLand.getReduce().add(i);
        }
        return newLand;
    }
}
